#include "request.h"

Request::Request(int timeout)
    : m_timeout(timeout),
    m_startTime(std::chrono::steady_clock::now()),
    m_endTime(std::chrono::steady_clock::now()),
    m_msg(nullptr),
    m_res(nullptr),
    m_onReply(nullptr)
{

}

Request::Request(const OnReply &onReply)
    : m_timeout(0),
    m_startTime(std::chrono::steady_clock::now()),
    m_endTime(std::chrono::steady_clock::now()),
    m_msg(nullptr),
    m_res(nullptr),
    m_onReply(onReply)
{

}

std::shared_ptr<Message> &Request::message()
{
    return m_msg;
}

void Request::setMessage(const std::shared_ptr<Message> &msg)
{
    m_msg = msg;
}

void Request::setMessage(std::shared_ptr<Message> &&msg)
{
    m_msg.swap(msg);
}

std::shared_ptr<Response> &Request::result()
{
    return m_res;
}

void Request::setResult(const std::shared_ptr<Response> &ret)
{
    m_endTime = std::chrono::steady_clock::now();
    m_res = ret;
    reply();
}

void Request::setResult(std::shared_ptr<Response> &&ret)
{
    m_endTime = std::chrono::steady_clock::now();
    m_res.swap(ret);
    reply();
}

bool Request::finished() const
{
    return m_res != nullptr;
}

bool Request::isTimeout() const
{
    if(finished()) {
        return isTimeout(m_endTime);
    }
    return false;
}

bool Request::isTimeout(std::chrono::steady_clock::time_point now) const
{
    return m_timeout > 0 && std::chrono::duration_cast<std::chrono::milliseconds>(now - m_startTime).count() > m_timeout;
}

void Request::wait()
{
    auto f = m_pro.get_future();
    if(f.valid()) {
        f.wait_for(std::chrono::milliseconds(m_timeout*2));
    }
}

void Request::reply()
{
    if(m_onReply) {
        m_onReply(m_res);
    } else {
        m_pro.set_value();
    }
}
